//
//  class_demo.cpp
//  cpp_learn
//
//  Created by 李贺 on 2021/12/17.
//

#include "class_demo.hpp"

namespace make_first_class_demo {

struct Sales_data {
    
    Sales_data() = default;
    Sales_data(const string &s): bookNo(s){
        
    }
    Sales_data(const string &s,unsigned n,double p){
        this->bookNo = s;
        this->units_sold = n;
        this->revenue = p;
    }
    
    Sales_data(istream & input) {
        
    }
    
    string isbn() const {
        return bookNo;
    }
    
    Sales_data & combine(const Sales_data &) {
        return *this;
    }

    double avg_price() const {
        return revenue;
    }
    
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

// const 修饰
void test_class_pointer() {
    Sales_data s1;
    
    // 这个说明p指向的 Sales_data 对象不能改变其属性值
    // p 能够指向其他对象
    const Sales_data *p = new Sales_data();
    p = &s1;
    
    // p1 指针不能指向其他变量,但是 p1 指针指向的Sales_data 对象的属性可以变
    Sales_data * const p1 = new Sales_data();
    p1->bookNo = string("fuckno");
    
    // 都不可变
    const Sales_data * const p2 = new Sales_data();
}

}

namespace make_class_demo1 {
class Sales_data {
public:
    Sales_data() = default;
    Sales_data(const string &s): bookNo(s){
        
    }
    Sales_data(const string &s,unsigned n,double p){
        this->bookNo = s;
        this->units_sold = n;
        this->revenue = p;
    }
    
    Sales_data(istream & input) {
        
    }
    
    string isbn() const {
        return bookNo;
    }
    
    Sales_data & combine(const Sales_data &) {
        return *this;
    }
    
private:
    double avg_price() const {
        return revenue;
    }
    
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};


void f();


class Screen {
public:
    typedef std:: string::size_type pos;
    using pos1 = string::size_type;
    using ScreenIndex = string:: size_type;
    friend class Window;
    friend void f() {
        
    }
    Screen(){
        f();
    }
    
    void g();
    void h();
private:
    pos cursor;
    pos1 height, width;
    string contents;
};

class Window {
    void clear(Screen &s);
};

void Window::clear(Screen &s) {
    cout << s.cursor << endl;
}

void Screen:: g() {
    f();
}

void Screen::h(){
    f();
}



}

namespace make_second_class_demo{
class Student;

class Teacher {
public:
    void clear(Student &s);
};

// friend 有缘函数
class Student {
public:
    
    Student() {
        this->name = "kk";
        this->likes = vector<string>();
    }
    
    Student(string name,vector<string> likes): name(name), likes(likes) {
        
    }
    
    friend void Teacher::clear(Student &s);
    string name;
    vector<string> likes;
    
    ~Student() {
        cout << "Student deinit" << endl;
    }
    
};

void Teacher::clear(Student &s) {
    cout << s.name << endl;
}

// new delete
void test_student_new() {
    vector<string> likes = vector<string>();
    Student *stu = new Student{"寒寒",likes};
    stu->name = "你是猴子吗";
    cout << stu->name << endl;
    delete stu;
}

// new[] delete[]
void test_student_new_delete() {
    vector<string> likes = vector<string>();
    // 生成的是数组
    Student *stu = new Student[3]{Student{"meimei0",likes}};
    stu->name = "yigexiaohouzi";
    (stu + 1)->name = "lanlan";
    (stu + 2)->name = "hanhan";
    cout << stu->name << endl;
    cout << (stu + 1)->name << endl;
    cout << (stu + 2)->name << endl;
    // delete 的也是数组
    delete [] stu;
}

// 智能指针
void test_student_share() {
    vector<string> likes = vector<string>();
    shared_ptr<Student> stu = make_shared<Student>("韩么美",likes);
    stu->name = "我从东土大唐而来";
    cout << stu->name << endl;
}

// 智能指针
void test_student_share_delete() {
    vector<string> likes = vector<string>();
    Student *stu = new Student{"dashabi",likes};
    stu->name = "我从东土大唐而来";
    shared_ptr<Student> stu1(stu);
    cout << stu->name << endl;
    
    stu1->name = "干你娘的傻逼";
    cout << stu1->name << endl;
    
    shared_ptr<Student> stu2 = stu1;
    stu2->name = "caonimade";
    cout << stu2->name<< endl;
    
    
    shared_ptr<Student> stu3(stu2);
    stu3->name = "stu3 name";
    cout << stu3->name << endl;
    
    shared_ptr<Student> stu4;
    stu4 = stu3;
    stu4->name = "stu4 name";
    cout << stu4->name << endl;

    // 一旦一个指针交给只能指针管理,就不用再去delete 指针,否则会过度释放指针
//    delete stu;
}

}


// 重载对象操作符
namespace make_third_class_demo {

class Student {
    
public:
    int age;
    Student(int age): age(age){
        
    }
    // + 操作符重载
    Student operator+(const Student &stu) {
        Student temp(stu.age);
        temp.age = this->age + stu.age;
        return temp;
    }
};

void test_op() {
    Student stu1(10);
    Student stu2(20);
    Student stu3 = stu1 + stu2;
    cout << stu3.age << endl;
}

}

// 重载全局操作符
namespace make_forth_class_demo {

class Student {
    
private:
    int age;
public:
    
    Student(int age): age(age){
        
    }
    // 声明某个全局函数为友元函数, 可以改变类的私有成员,仅仅是来做一个声明
    friend Student operator+(const Student &stu1,const Student &stu2);
    
    void print_age(){
        cout << age << endl;
    }
    
};

// 声明全局函数
Student operator+(const Student &stu1,const Student &stu2);

// 实现全局函数
Student operator+(const Student &stu1,const Student &stu2){
    Student stu3(stu1.age);
    stu3.age = stu1.age + stu2.age;
    return stu3;
}

void test_op() {
    Student stu(10);
    Student stu1(30);
    Student stu2 = stu + stu1;
    stu2.print_age();
}

}


